package com.mybatis.boost.mapper.util.sql;

import tk.mybatis.mapper.entity.EntityColumn;

import static com.mybatis.boost.mapper.util.OGNL.CHECK_FOR_NULL;
import static com.mybatis.boost.mapper.util.sql.SqlUtil.getEntityPrefix;
import static java.lang.String.format;
import static tk.mybatis.mapper.mapperhelper.EntityHelper.getColumns;
import static tk.mybatis.mapper.mapperhelper.EntityHelper.getPKColumns;

/**
 * @author jearton
 * @since 2017/2/10
 */
public abstract class UpdateSqlUtil {

    public static String checkPKValue(Class<?> entityClass, String parameterName) {
        return getPKColumns(entityClass).stream()
                .map(column -> {
                    String ognlParameter = getEntityPrefix(parameterName) + column.getProperty();
                    String exp = format(CHECK_FOR_NULL, ognlParameter, "'id must not be null for update'");
                    return "<if test=\"" + exp + "\"/>\n";
                })
                .reduce(String::concat)
                .orElse("");
    }

    /**
     * update tableName - 动态表名
     *
     * @param defaultTableName 默认表名
     * @param parameterName    方法参数名
     */
    public static String updateTable(Class<?> entityClass, String defaultTableName, String parameterName) {
        return "UPDATE " + SqlUtil.getDynamicTableName(entityClass, defaultTableName, parameterName) + " ";
    }

    /**
     * update set列
     *
     * @param entityClass 实体类
     */
    public static String updateSetColumns(Class<?> entityClass) {
        return "<set>" + _getColumnSetPairs(entityClass) + "</set>";
    }

    /**
     * update set单列
     */
    public static String updateSetSingleColumn(Class<?> entityClass) {
        return "<set>" + SqlUtil.getSingleColumnPair(entityClass) + "</set>";
    }

    /**
     * ON DUPLICATE KEY UPDATE column1=xxx, column2=xxx, column3=xxx
     *
     * @param entityClass 实体类
     */
    public static String onDuplicateKeyUpdate(Class<?> entityClass) {
        return "<trim prefix=\" ON DUPLICATE KEY UPDATE \" suffixOverrides=\",\">" + _getColumnSetPairs(entityClass) + "</trim>";
    }

    /**
     * cloumn1 = xxx, cloumn2 = xxx, cloumn3 = xxx
     *
     * @param entityClass 实体类
     */
    private static String _getColumnSetPairs(Class<?> entityClass) {
        return getColumns(entityClass).stream()
                .filter(column -> !column.isId() && !column.isUuid() && column.isUpdatable())
                .map(column -> {
                    String content = column.getColumnEqualsHolder("record") + ", ";
                    if (SqlUtil.isNotNull(column)) {
                        //当数据库列定义为NOT NULL，必须加上!=null的判断
                        return SqlUtil.getIfNotNull("record", column, content);
                    } else {
                        return _getIfAllowUpdateToNull(column, content);
                    }
                })
                .reduce(String::concat)
                .orElse("");
    }


    /**
     * @param column  数据库列
     * @param content 条件满足时的内容
     */
    private static String _getIfAllowUpdateToNull(EntityColumn column, String content) {
        String template = "<choose><when test='allowUpdateToNull'>%s</when><otherwise><if test='%s != null'>%s</if></otherwise></choose>";
        return format(template, content, "record." + column.getProperty(), content);
    }
}
